﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GmModelFamily.h"
#include "OwnerPtr.h"
#include "IFamilySketchPlane.h"

namespace gcmp
{
    class IDocument;
    class IGraphicsNodeReference;
}

namespace gfam
{
    class IFamilySketch2D;
    class IFamilySketchPlane;
    class IFamilyGeometryConstraint;
    class IFamilyConstraint;
    class IFamilyCoincidentConstraint;
    enum class FamilyConstraintType;
    enum class FamilyConstraintReferenceType;
}

namespace gfam
{

    class GCMP_MODEL_FAMILY_EXPORT FamilyConstraintUtils
    {
    public:
        /// \brief 添加约束
        ///
        /// \param pDocument 文档
        /// \param constraintType 约束类型
        /// \param curveId1       曲线1id
        /// \param geomType1      引用的曲线1类型
        /// \param curveId2       曲线2id
        /// \param geomType2      引用的曲线2类型
        /// \param pSketchPlane   草图平面
        /// \param pSketch        草图
        /// \param sketchAxis     草图轴线索引， -1表示不引用
        static void AddConstraint(gcmp::IDocument* pDocument, FamilyConstraintType constraintType
            , const gcmp::ElementId& curveId1, FamilyConstraintReferenceType geomType1, const gcmp::ElementId& curveId2, FamilyConstraintReferenceType geomType2
            , const IFamilySketchPlane* pSketchPlane, const IFamilySketch2D* pSketch, int sketchAxis = -1);

        /// \brief 添加共点约束
        ///
        /// \param pDocument    文档
        /// \param curveId1     曲线1id
        /// \param geomType1    引用的曲线1类型
        /// \param curveId2     曲线2id
        /// \param geomType2    引用的曲线2类型
        /// \param pSketchPlane 草图平面
        /// \param pSketch      草图
        /// \return  共点约束
        static IFamilyCoincidentConstraint* AddConstraintAsCoincidentPoints(gcmp::IDocument* pDocument,
            const gcmp::ElementId& curveId1, FamilyConstraintReferenceType geomType1, const gcmp::ElementId& curveId2, FamilyConstraintReferenceType geomType2
            , const IFamilySketchPlane* pSketchPlane, const IFamilySketch2D* pSketch);

        /// \brief 草图外添加共点约束
        ///
        /// \param pDocument 文档
        /// \param coord     坐标系 
        /// \param curveId1  曲线1id
        /// \param geomType1 引用曲线1类型
        /// \param nodeId1   引用曲线1图形节点id
        /// \param curveId2  曲线2id
        /// \param geomType2 引用曲线2类型
        /// \param nodeId2   引用曲线2图形节点id
        /// \return 共点约束
        static IFamilyCoincidentConstraint* AddCoincidentConstraintOutOfSketch(gcmp::IDocument* pDocument, const gcmp::Coordinate3d& coord,
            const gcmp::ElementId& curveId1, FamilyConstraintReferenceType geomType1, const gcmp::GraphicsNodeId& nodeId1,
            const gcmp::ElementId& curveId2, FamilyConstraintReferenceType geomType2, const gcmp::GraphicsNodeId& nodeId2);


        /// \brief 添加几何约束，支持草图内和草图外两种情况
        /// 有两个引用对象的几何约束
        ///
        /// \param pDocument       文档
        /// \param constraintType  约束类型
        /// \param nodeReference1  第一个对象的节点引用
        /// \param nodeReference2  第二个对象的节点引用
        /// \param sketchPlaneId   草图平面id
        /// \param sketchId        草图id
        /// \param coord           坐标系
        /// \return                几何约束
        static IFamilyGeometryConstraint* AddGeometryConstraint(gcmp::IDocument* pDocument, FamilyConstraintType constraintType,
            const gcmp::IGraphicsNodeReference& nodeReference1, const gcmp::IGraphicsNodeReference& nodeReference2,
            const gcmp::ElementId& sketchPlaneId, const gcmp::ElementId& sketchId, const gcmp::Coordinate3d& coord = gcmp::Coordinate3d());

        /// \brief 添加几何约束，支持草图内和草图外两种情况
        /// 有三个引用对象的几何约束
        ///
        /// \param pDocument       文档
        /// \param constraintType  约束类型
        /// \param nodeReference1  第一个对象的节点引用
        /// \param nodeReference2  第二个对象的节点引用
        /// \param nodeReference3  第三个对象的节点引用
        /// \param sketchPlaneId   草图平面id
        /// \param sketchId        草图id
        /// \param coord           坐标系
        /// \return                几何约束
        static IFamilyGeometryConstraint* AddGeometryConstraint(gcmp::IDocument* pDocument, FamilyConstraintType constraintType,
            const gcmp::IGraphicsNodeReference& nodeReference1, const gcmp::IGraphicsNodeReference& nodeReference2, const gcmp::IGraphicsNodeReference& nodeReference3,
            const gcmp::ElementId& sketchPlaneId, const gcmp::ElementId& sketchId, const gcmp::Coordinate3d& coord = gcmp::Coordinate3d());


        /// \brief 添加固定约束，支持草图内和草图外两种情况
        /// 有一个引用对象的几何约束
        ///
        /// \param pDocument       文档
        /// \param constraintType  约束类型
        /// \param nodeReference1  第一个对象的节点引用
        /// \param sketchId        草图id
        /// \param sketchPlaneId   草图平面id
        /// \return                几何约束
        static IFamilyGeometryConstraint* AddPinnedConstraint(gcmp::IDocument* pDocument, const gcmp::IGraphicsNodeReference& gNodeReference, const gcmp::ElementId& sketchId, const gcmp::ElementId& sketchPlaneId);

        // \brief 是否已经添加相同的约束
        ///
        /// \param pDocument       文档
        /// \param pConstraint  待比较的约束指针
        /// \return   bool
        static bool IsConstraintExisting(const gcmp::IDocument* pDocument, const IFamilyConstraint *pConstraint);

        // \brief 判断在相同的对象上是否已经添加相同的约束，用于约束创建前检查
        ///
        /// \param pDocument       文档
        /// \param constraintType  约束类型
        /// \param refObjects  约束引用对象
        /// \return   bool
        static bool IsConstraintExisting(const gcmp::IDocument* pDocument, const FamilyConstraintType constraintType, const std::vector<gcmp::OwnerPtr<gcmp::IGraphicsNodeReference>> &refObjects);


        // \brief 显示约束符号
        ///
        /// \param pDocument       文档
        /// \param idConstraint  约束id
        /// \return   
        static void ShowConstraintSymbol(gcmp::IDocument* pDocument, gcmp::ElementId idConstraint);

        // \brief 隐藏约束符号
        ///
        /// \param pDocument       文档
        /// \param idConstraint  约束id
        /// \return   
        static void HideConstraintSymbol(gcmp::IDocument* pDocument, gcmp::ElementId idConstraint);


        // 判断距离比例值的符号
        static int CalcRatioSign(const gcmp::IDocument* pDocument, const gcmp::Coordinate3d& coord, gcmp::IGraphicsNodeReference *pRef1,
            gcmp::IGraphicsNodeReference *pRef2, gcmp::IGraphicsNodeReference *pRef3, gcmp::Vector3d& projDir);


        /// \brief 判断图元是否被固定
        ///
        /// \param pDocument       文档
        /// \param id  族对象id
        /// \return     
        static bool IsElementPinned(const gcmp::IDocument* pDocument, gcmp::ElementId id);

        
        /// \brief 为约束创建约束符号
        ///
        /// \param pElement  约束对象   
        static void CreateConstraintSymbol(const gcmp::IElement* pElement);


        /// \brief 为几何对象创建默认的约束Behavior
        ///
        /// 支持约束的几何对象需要创建 
        ///
        /// \param pElement  几何对象   
        /// \return 创建成功返回true否则返回false
        static  bool CreateDefaultConstraintBehavior(gcmp::IElement* pElement);

        /// \brief 为连续尺寸标注的相等符号设置命令Id
        ///
        /// \param commandId  命令Id
        static void SetClickCommandIdForEqualSymbol(std::wstring commandId);

    };
}

